#! /usr/bin/env python
# -*- coding: utf-8 -*-

import matplotlib
#matplotlib.use('Agg')

import matplotlib.pyplot as plt
import numpy as np
from sklearn.cluster import KMeans
import csv


def show_available_font():
    from matplotlib.font_manager import FontManager
    import subprocess
    fm = FontManager()
    mat_fonts = set(f.name for f in fm.ttflist)

    output = subprocess.check_output(
        'fc-list :lang=zh -f "%{family}\n"', shell=True)
    # print '*' * 10, '系统可用的中文字体', '*' * 10
    # print output
    zh_fonts = set(f.split(',', 1)[0] for f in output.split('\n'))
    available = mat_fonts & zh_fonts

    print '*' * 10, '可用的字体', '*' * 10
    for f in available:
        print f



def draw_pie_show_percentage(data,title,keep=0):
    p = plt.subplot()
    p.cla()
    product_id={}
    for id in data:
        count = product_id.get(id,0)
        count += 1
        product_id[id] = count

    #dict to list
    product_id_list=[]
    for k in product_id.keys():
        product_id_list.append((k,product_id[k]))
    #sort
    product_id_list.sort(key=lambda x:x[1],reverse=True)

    if keep != 0 and keep < len(product_id_list):
        # merge others
        count_others = 0
        for i in product_id_list[keep:]:
            count_others += i[1]

        product_id_list = product_id_list[:keep]
        product_id_list.append(('Others',count_others))
    # Pie chart, where the slices will be ordered and plotted counter-clockwise:
    all_count = 0
    for i in product_id_list:
        all_count += i[1]
    all_count /= 100.0
    labels = []
    sizes = []
    for i in product_id_list:
        labels.append(i[0])
        sizes.append(i[1]/all_count)

    #explode = (0, 0.1, 0)  # only "explode" the 2nd slice (i.e. 'Hogs')
    p.set_title(title)
    _p = p.pie(sizes, labels=labels, autopct='%1.1f%%',
            shadow=True, startangle=90)
    #p.axis('equal')  # Equal aspect ratio ensures that pie is drawn as a circle.
    #p.legend()
    plt.savefig("dataset/s-roaming/tmp/" + title + "_pie.jpg", figsize=(11, 10), dpi=98)

def draw_bar(data,title,keep=0):
    p = plt.subplot()
    p.cla()
    product_id={}
    for id in data:
        count = product_id.get(id,0)
        count += 1
        product_id[id] = count

    #dict to list

    d=[]
    for k in product_id.keys():
        #labels.append(k)
        #quants.append(product_id[k])
        d.append((k,product_id[k]))

    #sort
    d.sort(key=lambda x: x[1], reverse=True)
    if keep!=0 and len(d) > keep:
        d = d[:keep]
    d = np.array(d)
    labels=d[:,0]
    quants=d[:,1]

    x_pos = np.arange(len(labels))
    p.bar(x_pos,quants)
    p.set_xticks(x_pos)
    p.set_xticklabels(labels)
    p.set_title(title)
    plt.savefig("dataset/s-roaming/tmp/" + title + "_bar.jpg", figsize=(11, 10), dpi=98)

def draw_plot(x,ys=[],ticks=None,labels=None,title="",keep=0,points=None):
    plt.figure(1,figsize=(19,10))
    p = plt.subplot()
    p.cla()
    #x1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
    #y1 = [30, 31, 31, 32, 33, 35, 35, 40, 47, 62, 99, 186, 480]

    #x2 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
    #y2 = [32, 32, 32, 33, 34, 34, 34, 34, 38, 43, 54, 69, 116, 271]


    #group_labels = ['64k', '128k', '256k', '512k', '1024k', '2048k', '4096k', '8M', '16M', '32M', '64M', '128M', '256M',
    #                '512M']
    #p.set_title('broadcast(b) vs join(r)')
    #p.set_xlabel('data size')
    #p.set_ylabel('time(s)')
    for _y in ys:
        p.plot(x, _y, 'b', label='join')

    if points is not None:
        p.scatter(points[:,0],points[:,1])
    #p.bar(x, y)
    #p.plot(x1, y1,'r', label='broadcast')
    #p.plot(x2, y2,'b',label='join')
    #p.set_yticks(np.linspace(0, 480, num=28))
    if ticks is not None:
        p.set_xticks(ticks)
    if labels is not None:
        p.set_xticklabels(labels)

    #p.legend(bbox_to_anchor=[0.3, 1])

    p.grid()
    #plt.subplots_adjust()
    plt.show()
    #plt.savefig("dataset/s-roaming/tmp/" + title + "_plot.jpg", figsize=(11, 10), dpi=98)

def read_data_and_preprocess_from_file(filename):
    f = open(filename, 'r')
    # f = open("dataset/s-roaming/Order-201607-201705.csv",'r')
    reader = csv.DictReader(f)
    data=[]
    for row in reader:
        i={}
        for item in row.items():
            name = str(item[0])
            value = str(item[1])
            if name == None:
                name = ""
            if value == None:
                value = ""
            i[name.strip()] = value.strip()
        data.append(i)
    return data

class Products:

    data=[]
    data_dict={}

    def __init__(self):
        self.read_product()

    def read_product(self):
        self.data = read_data_and_preprocess_from_file("dataset/s-roaming/263 PRD products list.csv")
        for row in self.data:
            self.data_dict[row['Product ID'].decode("utf-8")]=(row['productName'].decode("utf-8"),row['areaName'].decode("utf-8"),row['productPrice'].decode("utf-8"))

    def ID2Name(self,id=""):
        ret = self.data_dict.get(id)
        if ret is None:
            return ""
        return ret[0]

    def ID2Area(self,id=""):
        ret = self.data_dict.get(id)
        if ret is None:
            return ""
        return ret[1]

    def ID2Price(self,id=""):
        ret = self.data_dict.get(id)
        if ret is None:
            return ""
        return ret[2]

    def filter_by_area(self, data, area_s):
        _data=[]
        for i in data:
            _id = i.get("Product ID","")
            if self.ID2Area(_id) in area_s:
                _data.append(i)
        return _data


#print Products().ID2Name("P263_SGPDS0047SANX")


def get_col_as_list(data, col_name):
    cols=[]
    for row in data:
        cols.append(row[col_name])
    return cols



def show_billing(area):
    #fig.figure(figsize=(11, 10), dpi=98)
    data = read_data_and_preprocess_from_file("dataset/s-roaming/Billing-201607-201705.csv")
    P = Products()
    #data = Products().filter_by_area(data,u"中国香港")
    #data = Products().filter_by_area(data, u"韩国")
    data = P.filter_by_area(data, area)

    ###################################
    # show the percentage between success and fail
    #
    draw_pie_show_percentage(get_col_as_list(data, 'Billing Status'),""+ area[0] +' Billing Billing Status',2)
    draw_bar(get_col_as_list(data, 'Billing Status'),""+ area[0] +' Billing Billing Status',2)

    ###################################
    # show the percentage of each of product
    #
    cols=[]
    for row in data:
        if row['Billing Status'] == 'Success':
            cols.append(P.ID2Name(row['Product ID']))
    draw_pie_show_percentage(cols,""+ area[0] +' Billing Product ID',7)
    draw_bar(cols,""+ area[0] +' Billing Product ID')
    ###################################
    # show the percentage of each of price
    #
    draw_pie_show_percentage(get_col_as_list(data, 'Sales'),""+ area[0] +' Billing Sales',6)
    draw_bar(get_col_as_list(data, 'Sales'),""+ area[0] +' Billing Sales',6)
    ###################################
    # show the percentage of payment method
    #
    draw_pie_show_percentage(get_col_as_list(data, 'Payment Method'),""+ area[0] +' Billing Payment Method',6)
    draw_bar(get_col_as_list(data, 'Payment Method'),""+ area[0] +' Billing Payment Method',6)

    ###################################
    # show the percentage of user order
    #
    #draw_pie_show_percentage(plt.subplot2grid((5,4),(4,0)),get_col_as_list('User Account'),'User Account',6)
    draw_bar(get_col_as_list(data, 'User Account'),""+ area[0] +' Billing User Account',6)
    #fig.savefig("dataset/s-roaming/billing-"+area+".jpg",figsize=(11, 10), dpi=98)
    #plt.show()


def show_order(area):
    #fig = plt.gcf()
    #fig.figure()
    data = read_data_and_preprocess_from_file("dataset/s-roaming/Order-201607-201705.csv")
    ###################################
    # show the percentage of Account
    #
    '''
    _data=[]
    for row in data:
        if row['Order Status'] != 'Canceled' and row['Order Status'] != 'Overdue':
            _data.append(row)
    data = _data
    '''
    P = Products()
    #data = Products().filter_by_area(data,u"中国香港")
    #data = Products().filter_by_area(data, u"韩国")
    data = P.filter_by_area(data, area)
    #draw_pie_show_percentage(plt.subplot2grid((4,4),(0,0)),cols,'Account',50)
    draw_bar(get_col_as_list(data, 'Account'),""+ area[0] +' Order Account',10)

    ###################################
    # show the percentage of order status
    #
    draw_pie_show_percentage(get_col_as_list(data, 'Order Status'),""+ area[0] +' Order Order Status',6)
    draw_bar(get_col_as_list(data, 'Order Status'),""+ area[0] +' Order Order Status')

    ###################################
    # show the percentage of Product ID
    #
    prod = get_col_as_list(data, 'Product ID')
    names=[]

    for i in prod:
        names.append(P.ID2Name(i))
    draw_pie_show_percentage(names,""+ area[0] +' Order Product ID',6)
    draw_bar(names,""+ area[0] +' Order Product ID',5)

    ###################################
    # show the percentage of Order Price
    #
    draw_pie_show_percentage(get_col_as_list(data, 'Order Price'),""+ area[0] +' Order Order Price',6)
    draw_bar(get_col_as_list(data, 'Order Price'),""+ area[0] +' Order Order Price')
    #fig.savefig("dataset/s-roaming/order-" + area + ".jpg",figsize=(11, 10), dpi=98)
    #plt.show()

'''
show_order((u"香港",u"中国香港",u"香港澳门",u"澳门香港",u"全球"))
show_order((u"韩国",u"日韩",u"全球"))
show_order((u"泰国",u"全球"))

show_billing((u"香港",u"中国香港",u"香港澳门",u"澳门香港",u"全球"))
show_billing((u"韩国",u"日韩",u"全球"))
show_billing((u"泰国",u"全球"))
'''


def match_substrings_in_sentence(sentence="",strings=['']):
    for s in strings:
        if sentence.find(s) != -1:
            return True
    return False



def filter_item(data,country,excluded_substring):
    ret = []
    for item in data:
        if item['countryname'] != country:
            continue
        if match_substrings_in_sentence(item['产品名称'],excluded_substring) is False:
            continue
        ret.append(item)
    return ret


def read_flow_data(country):
    #data1 = read_data_and_preprocess_from_file("dataset/s-roaming/263 S漫游订单流量使用情况-20170221-20170502.csv")
    data2 = read_data_and_preprocess_from_file("dataset/s-roaming/263 S漫游流量使用统计20160705-20170220.csv")
    promotion_keys=('体验','测试','促销','不限流量','无限流量','discount','不限量')
    data2 = filter_item(data2,country,promotion_keys)
    import datetime


    user_id_as_key_index_as_value_for_each_item={}
    i = -1
    for item in data2:
        i += 1
        id = item['账户ID']
        v = user_id_as_key_index_as_value_for_each_item.get(id, None)
        if v is not None:
            v.append(i)
        else:
            user_id_as_key_index_as_value_for_each_item[id] = [i]

    order_id_as_key_index_as_value_for_each_item={}
    i = -1
    for item in data2:
        i += 1
        id = item['订单号']
        order_id_as_key_index_as_value_for_each_item[id] = i


    date_as_key_days_count_as_valus = {}

    for item in data2:
        t_str = item['登网时间']
        date_start = None
        #07/05/2016 10:27
        try:
            date_start = datetime.datetime.strptime(t_str, '%m/%d/%Y %H:%M')
            order_days_by_parent = False
        except Exception, reason:
            #print reason
            #continue
            order_days_by_parent = True

        if order_days_by_parent is True:
            _item = item
            while True:
                parent_id = _item['父类订单号']
                parent_index = order_id_as_key_index_as_value_for_each_item.get(parent_id,None)
                if parent_index is not None:
                    _item = data2[parent_index]
                else:
                    break

            t_start_str = _item['登网时间']
            t_end__str = item['到期时间']
            try:
                date_start = datetime.datetime.strptime(t_start_str, '%m/%d/%Y %H:%M')
                date_end = datetime.datetime.strptime(t_end__str, '%m/%d/%Y %H:%M')
            except Exception, reason:
                print reason
                continue
            days_last = (date_end - date_start).days

            for i in range(days_last):
                day_add = datetime.timedelta(days=i)
                _date = (date_start + day_add).strftime('%m/%d/%Y')
                n = date_as_key_days_count_as_valus.get(_date, 0)
                date_as_key_days_count_as_valus[_date] = (n + 1)
        else:
            days = int(item['流量天数'])
            for i in range(days):
                day_add = datetime.timedelta(days=i)
                _date = (date_start + day_add).strftime('%m/%d/%Y')
                n = date_as_key_days_count_as_valus.get(_date,0)
                date_as_key_days_count_as_valus[_date] = (n +1)
                #print _date.strftime('%m/%d/%Y')

    days = date_as_key_days_count_as_valus.keys()

    def cmp_datetime(a, b):
        a_datetime = datetime.datetime.strptime(a, '%m/%d/%Y')
        b_datetime = datetime.datetime.strptime(b, '%m/%d/%Y')

        if a_datetime > b_datetime:
            return 1
        elif a_datetime < b_datetime:
            return -1
        else:
            return 0

    days.sort(cmp=cmp_datetime)

    x = []
    y = []
    x_date=[]
    begin_date = datetime.datetime.strptime(days[0], '%m/%d/%Y')
    end_date = datetime.datetime.strptime(days[-1], '%m/%d/%Y')

    all_days_count = (end_date - begin_date).days + 1
    for i in range(all_days_count):
        cur = datetime.datetime.strptime(days[0], '%m/%d/%Y') + datetime.timedelta(days=i)
        count_in_this_day = date_as_key_days_count_as_valus.get(cur.strftime('%m/%d/%Y'),0)
        y.append(count_in_this_day)
        x.append(i)
        #x_date.append(cur.strftime('%m/%d/%Y'))
    ticks = np.linspace(1, len(x), num=30)
    labels=[]
    #ticks =
    #x = np.linspace(1,len(x),step=1.0)
    # 统统计时间上的使用需求量(单个国家,不考虑优惠)
    # 可以反应 某个时间出国的热度
    i = 1
    all_num = []
    for n in y:
        all_num.append([i,n])
        i+=1
    km = KMeans(n_clusters=20, random_state=9).fit(all_num)

    draw_plot(x, [y],points=km.cluster_centers_)


    #draw count of orders plot in week(0~6 = mon~sun)
    weeks=[0,0,0,0,0,0,0]
    all_days_count = (end_date - begin_date).days + 1
    for i in range(all_days_count):
        cur = datetime.datetime.strptime(days[0], '%m/%d/%Y') + datetime.timedelta(days=i)
        weeks[cur.weekday()] += y[i]

    draw_plot([1,2,3,4,5,6,7], [weeks],ticks=[1,2,3,4,5,6,7],labels=['Mon','Tue','Wed','Thu','Fri','Sat','Sun'])

    # draw count of orders box plot in week(0~6 = mon~sun)
    weeks = [[], [], [], [], [], [], []]
    all_days_count = (end_date - begin_date).days + 1
    for i in range(all_days_count):
        cur = datetime.datetime.strptime(days[0], '%m/%d/%Y') + datetime.timedelta(days=i)
        weeks[cur.weekday()].append(y[i])

    plt.figure(figsize=(8,6))
    plt.boxplot(weeks)
    plt.xticks([1,2,3,4,5,6,7],['Mon','Tue','Wed','Thu','Fri','Sat','Sun'])
    plt.show()


    #draw count of orders plot by week (sum day's num by week)
    week_num=[]
    all_days_count = (end_date - begin_date).days + 1
    all_in_week=0
    ticks=[]
    ticks_num=0
    labels=[]
    for i in range(all_days_count):
        cur = datetime.datetime.strptime(days[0], '%m/%d/%Y') + datetime.timedelta(days=i)
        if cur.weekday() == 0:
            week_num.append(all_in_week)
            all_in_week = 0
            ticks.append(ticks_num)
            ticks_num += 1
            labels.append(cur.strftime('%m/%d'))
        else:
            all_in_week += y[i]

    draw_plot([i for i in range(len(week_num))], [week_num],ticks=ticks,labels=labels)

    # 统计每个账户在时间上持续的天数
    # 反应这个人这次出国待几天

    all_user_count = len(user_id_as_key_index_as_value_for_each_item.keys())




    x_as_date_y_as_user_id = np.zeros((all_user_count,all_days_count))

    users_id = user_id_as_key_index_as_value_for_each_item.keys()
    user_index = 0
    for _id in users_id:
        indexs = user_id_as_key_index_as_value_for_each_item[_id]
        for i in indexs:
            item = data2[i]

            t_str = item['登网时间']
            date_start = None
            # 07/05/2016 10:27
            try:
                date_start = datetime.datetime.strptime(t_str, '%m/%d/%Y %H:%M')
                order_days_by_parent = False
            except Exception, reason:
                #print reason
                order_days_by_parent = True

            if order_days_by_parent is True:
                _item = item
                while True:
                    parent_id = _item['父类订单号']
                    parent_index = order_id_as_key_index_as_value_for_each_item.get(parent_id,None)
                    if parent_index is not None:
                        _item = data2[parent_index]
                    else:
                        break

                t_start_str = _item['登网时间']
                t_end__str = item['到期时间']
                try:
                    date_start = datetime.datetime.strptime(t_start_str, '%m/%d/%Y %H:%M')
                    date_end = datetime.datetime.strptime(t_end__str, '%m/%d/%Y %H:%M')
                except Exception, reason:
                    print reason
                    continue
                days_last = (date_end - date_start).days
                days_index_base = (date_start - begin_date).days

                for i in range(days_last):
                    cur_day_index = days_index_base + i
                    x_as_date_y_as_user_id[user_index][cur_day_index] = 1
            else:
                days_index_base = (date_start - begin_date).days

                days_last = int(item['流量天数'])
                for i in range(days_last):
                    cur_day_index = days_index_base + i
                    x_as_date_y_as_user_id[user_index][cur_day_index] = 1
        user_index += 1

    serial_days_type_count = 17
    percentage_of_serial_days = np.zeros((serial_days_type_count, all_days_count))
    for _day in range(all_days_count):
        serial_days_result = np.zeros((serial_days_type_count))
        for _user in range(all_user_count):
            _serial_days = 0
            for day_offset in range(_day,all_days_count):
                is_under_using = x_as_date_y_as_user_id[_user][day_offset]
                if is_under_using == 0:
                    break
                x_as_date_y_as_user_id[_user][day_offset] = 0
                _serial_days += 1
            if _serial_days != 0:
                serial_days_result[_serial_days] += 1

        #_sum = np.sum(serial_days_result)
        #for i in range(serial_days_type_count):
        #    percentage_of_serial_days[i][_day] = (serial_days_result[i] * 100 / _sum)

        for i in range(serial_days_type_count):
            percentage_of_serial_days[i][_day] = (serial_days_result[i])

    #for i in range(1,serial_days_type_count):
    #    percentage_of_serial_days[i] = percentage_of_serial_days[i]+ percentage_of_serial_days[i-1]
    #draw_plot(x, percentage_of_serial_days)



    from mpl_toolkits.mplot3d import Axes3D

    _data_3d = []
    for i in range(serial_days_type_count):
        for _day in range(all_days_count):
            count = percentage_of_serial_days[i][_day]
            if count != 0:
                _data_3d.append([i,_day,count])

    _data_3d = np.array(_data_3d)
    from sklearn import preprocessing
    _data_3d = preprocessing.scale(_data_3d)

    km = KMeans(n_clusters=9, random_state=9).fit(_data_3d)

    fig = plt.figure(figsize=(4, 3))
    plt.clf()
    ax = Axes3D(fig, rect=[0, 0, .95, 1], elev=48, azim=134)

    plt.cla()

    labels = km.labels_
    X = _data_3d
    ax.scatter(X[:, 0], X[:, 1], X[:, 2], c=labels.astype(np.float))
    ax.scatter(km.cluster_centers_[:,0], km.cluster_centers_[:, 1], km.cluster_centers_[:, 2],c="r",marker="x")
    #ax.w_xaxis.set_ticklabels([])
    #ax.w_yaxis.set_ticklabels([])
    #ax.w_zaxis.set_ticklabels([])
    ax.set_xlabel('Serial days')
    ax.set_ylabel('Date')
    ax.set_zlabel('Count')
    plt.show()

    pass







read_flow_data('香港')

